package jt

import (
	"fmt"
	"reflect"
)

func _byteMarshal(b *jtBytes, v interface{}) byte {
	if v == nil {
		return b.toByte()
	}
	n := byte(reflect.ValueOf(v).Interface().(float64))
	b.addByte(1)
	b.addByte(n)
	return n
}

func _wordMarshal(b *jtBytes, v interface{}) uint16 {
	if v == nil {
		return b.toWord()
	}
	n := uint16(reflect.ValueOf(v).Interface().(float64))
	b.addByte(1)
	b.addWord(n)
	return n
}

func _dWordMarshal(b *jtBytes, v interface{}) uint32 {
	if v == nil {
		return b.toDWord()
	}
	n := uint32(reflect.ValueOf(v).Interface().(float64))
	b.addByte(4)
	b.addDWord(n)
	return n
}

func _bytesMarshal(b *jtBytes, v interface{}) []byte {
	if v == nil {
		return b.toBytes()
	}
	data := reflect.ValueOf(v).Interface().([]byte)
	b.addByte(uint8(len(data)))
	b.addBytes(data)
	return data
}

func _stringMarshal(b *jtBytes, v interface{}) string {
	if v == nil {
		return toUTF8(b.Bytes)
	}
	s := reflect.ValueOf(v).Interface().(string)
	b.addString(s, 1)
	return s
}

type jtParamChl struct {
	Live struct {
		Encode        uint8  `json:"encode"`
		Res           uint8  `json:"res"`
		FrameInterval uint16 `json:"frameInterval"`
		FrameRate     uint8  `json:"frameRate"`
		BitRate       uint16 `json:"bitRate"`
	} `json:"live"`
	Storage struct {
		Encode        uint8  `json:"encode"`
		Res           uint8  `json:"res"`
		FrameInterval uint16 `json:"frameInterval"`
		FrameRate     uint8  `json:"frameRate"`
		BitRate       uint16 `json:"bitRate"`
	} `json:"storage"`
	Osd uint16 `json:"osd"`
}

// 音视频参数设置
type jtParam0075 struct {
	jtParamChl
	AudioOut uint8 `json:"audioOut"`
}

func _0075Marshal(b *jtBytes, v interface{}) (r jtParam0075) {
	if v == nil {
		r.Live.Encode = b.toByte()
		r.Live.Res = b.toByte()
		r.Live.FrameInterval = b.toWord()
		r.Live.FrameRate = b.toByte()
		r.Live.BitRate = b.toWord()
		r.Storage.Encode = b.toByte()
		r.Storage.Res = b.toByte()
		r.Storage.FrameInterval = b.toWord()
		r.Storage.FrameRate = b.toByte()
		r.Storage.BitRate = b.toWord()
		r.Osd = b.toWord()
		r.AudioOut = b.toByte()
		return
	}
	if err := jsonVal(v, &r); err == nil {
		b.addByte(r.Live.Encode)
		b.addByte(r.Live.Res)
		b.addWord(r.Live.FrameInterval)
		b.addByte(r.Live.FrameRate)
		b.addWord(r.Live.BitRate)
		b.addByte(r.Storage.Encode)
		b.addByte(r.Storage.Res)
		b.addWord(r.Storage.FrameInterval)
		b.addByte(r.Storage.FrameRate)
		b.addWord(r.Storage.BitRate)
		b.addWord(r.Osd)
		b.addByte(r.AudioOut)
	}
	return
}

type jt0076Chnanel struct {
	Physical uint8 `json:"physical"`
	Logical  uint8 `json:"logical"`
	Type     uint8 `json:"type"`
	Cloud    uint8 `json:"cloud"`
}

// 音视频通道列表设置
type jtParam0076 struct {
	Total    uint8           `json:"total"`
	ANum     uint8           `json:"anum"`
	VNum     uint8           `json:"vnum"`
	Channels []jt0076Chnanel `json:"channels"`
}

func _0076Marshal(b *jtBytes, v interface{}) (r jtParam0076) {
	if v == nil {
		r.Total = b.toByte()
		r.ANum = b.toByte()
		r.VNum = b.toByte()
		chns := int(r.Total + r.ANum + r.VNum)
		for i := 0; i < chns; i++ {
			ch := jt0076Chnanel{}
			ch.Physical = b.toByte()
			ch.Logical = b.toByte()
			ch.Type = b.toByte()
			ch.Cloud = b.toByte()
			r.Channels = append(r.Channels, ch)
		}
		return
	}
	jsonVal(v, &r) // 不允许设置
	return r
}

// 单独通道视频参数
type jtParam0077 struct {
	Channels []jtParamChl `json:"channels"`
}

func _0077Marshal(b *jtBytes, v interface{}) (r jtParam0077) {
	if v == nil {
		count := b.toByte()
		for i := uint8(0); i < count; i++ {
			var ch jtParamChl
			ch.Live.Encode = b.toByte()
			ch.Live.Res = b.toByte()
			ch.Live.FrameInterval = b.toWord()
			ch.Live.FrameRate = b.toByte()
			ch.Live.BitRate = b.toWord()
			ch.Storage.Encode = b.toByte()
			ch.Storage.Res = b.toByte()
			ch.Storage.FrameInterval = b.toWord()
			ch.Storage.FrameRate = b.toByte()
			ch.Storage.BitRate = b.toWord()
			ch.Osd = b.toWord()
			r.Channels = append(r.Channels, ch)
		}
	}
	return
}

// 特殊报警录像参数设置
type jtParam0079 struct {
	StoThreshold uint8 `json:"stoThreshold"`
	Duration     uint8 `json:"duration"`
	StartTime    uint8 `json:"startTime"`
}

func _0079Marshal(b *jtBytes, v interface{}) (r jtParam0079) {
	if v == nil {
		r.StoThreshold = b.toByte()
		r.Duration = b.toByte()
		r.StartTime = b.toByte()
	}
	return
}

// 视频分析报警参数定义
type jtParam007B struct {
	PeopleNum    uint8 `json:"peopleNum"`
	FatThreshold uint8 `json:"fatThreshold"`
	StartTime    uint8 `json:"startTime"`
}

func _007BMarshal(b *jtBytes, v interface{}) (r jtParam007B) {
	if v == nil {
		r.PeopleNum = b.toByte()
		r.FatThreshold = b.toByte()
		r.StartTime = b.toByte()
	}
	return
}

// 终端休眠唤醒模式
type jtParam007C struct {
	WakeMode  uint8 `json:"wakeMode"`
	WakeType  uint8 `json:"wakeType"`
	WakeTimed uint8 `json:"wakeTimed"`
}

func _007CMarshal(b *jtBytes, v interface{}) (r jtParam007C) {
	if v == nil {
		r.WakeMode = b.toByte()
		r.WakeType = b.toByte()
		r.WakeTimed = b.toByte()
	}
	return
}

type jtAlarmVp struct {
	VideoRecordingTime uint8 `json:"videoRecordTime"` // 前后视频录制时间
	PhotosNumber       uint8 `json:"photosNumber"`    //拍照张数
	PhotoInterval      uint8 `json:"photoInterval"`   // 拍照间隔
}

func (o jtAlarmVp) Marshal(b *jtBytes) {
	b.addByte(o.VideoRecordingTime)
	b.addByte(o.PhotosNumber)
	b.addByte(o.PhotoInterval)
}

type jtGradedAlarm struct {
	GradedSpeedThreshold uint8 `json:"gradedSpeedThreshold"` // 分级速度阈值
	jtAlarmVp
}

func (o jtGradedAlarm) Marshal(b *jtBytes) {
	b.addByte(o.GradedSpeedThreshold)
	o.jtAlarmVp.Marshal(b)
}

func (o *jtGradedAlarm) decode(b *jtBytes) {
	o.GradedSpeedThreshold = b.toByte()
	o.jtAlarmVp.decode(b)
}

func (o *jtAlarmVp) decode(b *jtBytes) {
	o.VideoRecordingTime = b.toByte()
	o.PhotosNumber = b.toByte()
	o.PhotoInterval = b.toByte()
}

func _adasMarshal(b *jtBytes, v interface{}) interface{} {
	r := struct {
		AlarmSpeedThresold uint8 `json:"alarmSpeedThresold"`
		AlarmAlertVolume   uint8 `json:"alarmAlertVolume"`
		ActiveTimedPhoto   struct {
			Interval         uint16 `json:"interval"`
			DistanceInterval uint16 `json:"distanceInterval"`
		} `json:"activeTimedPhoto"`
		SingleActive struct {
			PhotosNumber  uint8 `json:"photosNumber"`  //单次主动拍照张数
			PhotoInterval uint8 `json:"photoInterval"` //单次主动拍照时间间隔
		} `json:"singleActive"`
		PhotoResolution          uint8 `json:"photoResolution"`          //拍照分辨率
		VideoRecordingResolution uint8 `json:"videoRecordingResolution"` //视频录制分辨率
		AlarmEnabled             uint8 `json:"alarmEnabled"`             //报警使能
		EventEnable              uint8 `json:"eventEnable"`              //事件使能
		Reserved0                uint8 `json:"reserved0"`                //预留字段
		ObstaclAlarm             struct {
			DistanceThreshold uint8 `json:"distanceThreshold"` // 阈值
			jtGradedAlarm
		} `json:"obstaclAlarm"` // 障碍物报警
		FrequentLaneChangeAlarm struct {
			DeterminesTimePeriod uint8 `json:"determinesTimePeriod"` //判断时间段
			JudgmentsNumber      uint8 `json:"judgmentsNumber"`      //频繁变道报警判断次数
			jtGradedAlarm
		} `json:"frequentLaneChangeAlarm"` // 频繁变道报警
		LaneDepartureWarning  jtGradedAlarm `json:"laneDepartureWarning"`
		ForwardCollisionAlarm struct {
			TimeThreshold uint8 `json:"timeThreshold"` //前向碰撞报警时间阈值
			jtGradedAlarm
		} `json:"forwardCollisionAlarm"`
		PedestrianCollisionAlarm struct {
			TimeThreshold         uint8 `json:"timeThreshold"`         //行人碰撞报警时间阈值
			EnablesSpeedThreshold uint8 `json:"enablesSpeedThreshold"` //行人碰撞报警使能速度阈值
			jtAlarmVp
		} `json:"pedestrianCollisionAlarm"`
		VehicleDistanceMonitoringAlarm struct {
			DistanceThreshold uint8 `json:"distanceThreshold"` //车距监控报警距离阈值
			jtGradedAlarm
		} `json:"vehicleDistanceMonitoringAlarm"`
		RoadSignsRecognize struct {
			PhotoInterval uint8 `json:"photoInterval"` //道路标志识别拍照间隔
		} `json:"roadSignsRecognize"`
		Reserved [4]byte `json:"reserved"` //保留字段
	}{}
	if v == nil {
		r.AlarmSpeedThresold = b.toByte()
		r.AlarmAlertVolume = b.toByte()
		r.ActiveTimedPhoto.Interval = b.toWord()
		r.ActiveTimedPhoto.DistanceInterval = b.toWord()
		r.SingleActive.PhotosNumber = b.toByte()
		r.SingleActive.PhotoInterval = b.toByte()
		r.PhotoResolution = b.toByte()
		r.VideoRecordingResolution = b.toByte()
		r.AlarmEnabled = b.toByte()
		r.EventEnable = b.toByte()
		r.Reserved0 = b.toByte()
		r.ObstaclAlarm.DistanceThreshold = b.toByte()
		r.ObstaclAlarm.decode(b)
		r.FrequentLaneChangeAlarm.DeterminesTimePeriod = b.toByte()
		r.FrequentLaneChangeAlarm.JudgmentsNumber = b.toByte()
		r.FrequentLaneChangeAlarm.decode(b)
		r.LaneDepartureWarning.decode(b)
		r.ForwardCollisionAlarm.TimeThreshold = b.toByte()
		r.ForwardCollisionAlarm.decode(b)
		r.PedestrianCollisionAlarm.TimeThreshold = b.toByte()
		r.PedestrianCollisionAlarm.EnablesSpeedThreshold = b.toByte()
		r.PedestrianCollisionAlarm.decode(b)
		r.VehicleDistanceMonitoringAlarm.DistanceThreshold = b.toByte()
		r.VehicleDistanceMonitoringAlarm.decode(b)
		r.RoadSignsRecognize.PhotoInterval = b.toByte()
		b.toArray(4) //r.Reserved
		return r
	}
	if err := jsonVal(v, &r); err == nil {
		b.addByte(r.AlarmSpeedThresold)
		b.addByte(r.AlarmAlertVolume)
		b.addWord(r.ActiveTimedPhoto.Interval)
		b.addWord(r.ActiveTimedPhoto.DistanceInterval)
		b.addByte(r.SingleActive.PhotosNumber)
		b.addByte(r.SingleActive.PhotoInterval)
		b.addByte(r.PhotoResolution)
		b.addByte(r.VideoRecordingResolution)
		b.addByte(r.AlarmEnabled)
		b.addByte(r.EventEnable)
		b.addByte(r.Reserved0)
		b.addByte(r.ObstaclAlarm.DistanceThreshold)
		b.addByte(r.ObstaclAlarm.GradedSpeedThreshold)
		r.ObstaclAlarm.Marshal(b)
		b.addByte(r.FrequentLaneChangeAlarm.DeterminesTimePeriod)
		b.addByte(r.FrequentLaneChangeAlarm.JudgmentsNumber)
		r.FrequentLaneChangeAlarm.Marshal(b)
		r.LaneDepartureWarning.Marshal(b)
		b.addByte(r.ForwardCollisionAlarm.TimeThreshold)
		r.ForwardCollisionAlarm.Marshal(b)
		b.addByte(r.PedestrianCollisionAlarm.TimeThreshold)
		b.addByte(r.PedestrianCollisionAlarm.EnablesSpeedThreshold)
		r.PedestrianCollisionAlarm.Marshal(b)
		b.addByte(r.VehicleDistanceMonitoringAlarm.DistanceThreshold)
		r.VehicleDistanceMonitoringAlarm.Marshal(b)
		b.addByte(r.RoadSignsRecognize.PhotoInterval)
		b.addBytes(r.Reserved[:])
	}
	return r
}

func _dsmMarshal(b *jtBytes, v interface{}) interface{} {
	var r struct {
		AlarmSpeedThresold uint8 `json:"alarmSpeedThresold"`
		AlarmAlertVolume   uint8 `json:"alarmAlertVolume"`
		ActiveTimedPhoto   struct {
			Interval         uint16 `json:"interval"`
			DistanceInterval uint16 `json:"distanceInterval"`
		} `json:"activeTimedPhoto"`
		SingleActive struct {
			PhotosNumber  uint8 `json:"photosNumber"`  //单次主动拍照张数
			PhotoInterval uint8 `json:"photoInterval"` //单次主动拍照时间间隔
		} `json:"singleActive"`
		PhotoResolution                    uint8    `json:"photoResolution"`                    //拍照分辨率
		VideoRecordingResolution           uint8    `json:"videoRecordingResolution"`           //视频录制分辨率
		AlarmEnabled                       uint8    `json:"alarmEnabled"`                       //报警使能
		EventEnable                        uint8    `json:"eventEnable"`                        //事件使能
		SmokingAlarmDeterminesTimeInterval uint16   `json:"smokingAlarmDeterminesTimeInterval"` //吸烟报警判断时间间隔
		CallAlarmDetermineTimeInterval     uint16   `json:"callAlarmDetermineTimeInterval"`     // 接打电话报警判断时间间隔
		Reserved0                          [3]uint8 `json:"reserved0"`                          //预留字段

		FatigueDrivingAlarm         jtGradedAlarm `json:"fatigueDrivingAlarm"` // 疲劳驾驶报
		CallAlarm                   jtGradedAlarm `json:"callAlarm"`           // 接打电话报警
		SmokingAlarm                jtGradedAlarm `json:"smokingAlarm"`
		DistractedDrivingAlarm      jtGradedAlarm `json:"distractedDrivingAlarm"`
		AbnormalDrivingAlarm        jtGradedAlarm `json:"abnormalDrivingAlarm"`        // 驾驶行为异常
		DriverIdentificationTrigger uint8         `json:"driverIdentificationTrigger"` // 驾驶员身份识别触发
		Reserved                    [2]byte       `json:"reserved"`                    //保留字段
	}
	if v == nil {
		r.AlarmSpeedThresold = b.toByte()
		r.AlarmAlertVolume = b.toByte()
		r.ActiveTimedPhoto.Interval = b.toWord()
		r.ActiveTimedPhoto.DistanceInterval = b.toWord()
		r.SingleActive.PhotosNumber = b.toByte()
		r.SingleActive.PhotoInterval = b.toByte()
		r.PhotoResolution = b.toByte()
		r.VideoRecordingResolution = b.toByte()
		r.AlarmEnabled = b.toByte()
		r.EventEnable = b.toByte()
		r.SmokingAlarmDeterminesTimeInterval = b.toWord()
		r.CallAlarmDetermineTimeInterval = b.toWord()
		b.toArray(3) // r.Reserved0
		r.FatigueDrivingAlarm.decode(b)
		r.CallAlarm.decode(b)
		r.SmokingAlarm.decode(b)
		r.DistractedDrivingAlarm.decode(b)
		r.AbnormalDrivingAlarm.decode(b)
		r.DriverIdentificationTrigger = b.toByte()
		b.toArray(2) // r.Reserved
		return r
	}
	if err := jsonVal(v, &r); err == nil {
		b.addByte(r.AlarmSpeedThresold)
		b.addByte(r.AlarmAlertVolume)
		b.addWord(r.ActiveTimedPhoto.Interval)
		b.addWord(r.ActiveTimedPhoto.DistanceInterval)
		b.addByte(r.SingleActive.PhotosNumber)
		b.addByte(r.SingleActive.PhotoInterval)
		b.addByte(r.PhotoResolution)
		b.addByte(r.VideoRecordingResolution)
		b.addByte(r.AlarmEnabled)
		b.addByte(r.EventEnable)
		b.addWord(r.SmokingAlarmDeterminesTimeInterval)
		b.addWord(r.CallAlarmDetermineTimeInterval)
		b.addBytes(r.Reserved0[:])
		r.FatigueDrivingAlarm.Marshal(b)
		r.CallAlarm.Marshal(b)
		r.SmokingAlarm.Marshal(b)
		r.DistractedDrivingAlarm.Marshal(b)
		r.AbnormalDrivingAlarm.Marshal(b)
		b.addByte(r.DriverIdentificationTrigger)
		b.addBytes(r.Reserved[:])
	}
	return r
}

func _tpmsMarshal(b *jtBytes, v interface{}) interface{} {
	var r struct {
		tireSpecificationsModels       [12]byte `json:"-"`
		TireSpecificationsModels       string   `json:"tireSpecificationsModels"`       // 轮胎规格型号 [12]byte
		TirePressureUnits              uint16   `json:"tirePressureUnits"`              // 胎压单位
		NormalTirePressureValues       uint16   `json:"normalTirePressureValues"`       // 正常胎压值
		TirePressureUnbalanceThreshold uint16   `json:"tirePressureUnbalanceThreshold"` // 胎压不平衡门限
		SlowLeakThreshold              uint16   `json:"slowLeakThreshold"`              // 慢漏气门限
		LowPressureThreshold           uint16   `json:"lowPressureThreshold"`           // 低压阈值
		HighPressureThreshold          uint16   `json:"highPressureThreshold"`          // 高压阈值
		HighTemperatureThreshold       uint16   `json:"highTemperatureThreshold"`       // 高温阈值
		VoltageThreshold               uint16   `json:"voltageThreshold"`               // 电压阈值
		ScheduledReportingInterval     uint16   `json:"scheduledReportingInterval"`     // 定时上报时间间隔
		Reserved                       [6]byte  `json:"reserved"`
	}
	if v == nil {
		r.TireSpecificationsModels = toUTF8(b.toArray(12))
		r.TirePressureUnits = b.toWord()
		r.NormalTirePressureValues = b.toWord()
		r.TirePressureUnbalanceThreshold = b.toWord()
		r.SlowLeakThreshold = b.toWord()
		r.LowPressureThreshold = b.toWord()
		r.HighPressureThreshold = b.toWord()
		r.HighTemperatureThreshold = b.toWord()
		r.VoltageThreshold = b.toWord()
		r.ScheduledReportingInterval = b.toWord()
		b.toArray(6) // r.Reserved
		return r
	}
	if err := jsonVal(v, &r); err == nil {
		copy(r.tireSpecificationsModels[:], r.TireSpecificationsModels)
		b.addBytes(r.tireSpecificationsModels[:])
		b.addWord(r.TirePressureUnits)
		b.addWord(r.NormalTirePressureValues)
		b.addWord(r.TirePressureUnbalanceThreshold)
		b.addWord(r.SlowLeakThreshold)
		b.addWord(r.LowPressureThreshold)
		b.addWord(r.HighPressureThreshold)
		b.addWord(r.HighTemperatureThreshold)
		b.addWord(r.VoltageThreshold)
		b.addWord(r.ScheduledReportingInterval)
		b.addBytes(r.Reserved[:])
	}
	return r
}

func _bsdMarshal(b *jtBytes, v interface{}) interface{} {
	var r struct {
		RearApproachAlarmThreshold  uint8 `json:"rearApproachAlarmThreshold"`
		AheadApproachAlarmThreshold uint8 `json:"aheadApproachAlarmThreshold"`
	}
	if v == nil {
		r.RearApproachAlarmThreshold = b.toByte()
		r.AheadApproachAlarmThreshold = b.toByte()
		return r
	}
	if err := jsonVal(v, &r); err == nil {
		b.addByte(r.RearApproachAlarmThreshold)
		b.addByte(r.AheadApproachAlarmThreshold)
	}
	return r
}

// type jtParamCan struct {
// }

type jtParamItem struct {
	ID    string      `json:"codeId"`
	Value interface{} `json:"value,omitempty"`
}

type jtParameter struct {
	Data []jtParamItem `json:"data"`
}

func (jtParameter) Parse(id uint32, b *jtBytes, v interface{}) (r jtParamItem) {
	switch id {
	case 0x0001,
		0x0002,
		0x0003,
		0x0004,
		0x0005,
		0x0006,
		0x0007,
		0x0018,
		0x0019,
		0x001B,
		0x001C,
		0x0020,
		0x0021,
		0x0022,
		0x0023,
		0x0024,
		0x0025,
		0x0026,
		0x0027,
		0x0028,
		0x0029,
		0x002A,
		0x002B,
		0x002C,
		0x002D,
		0x002E,
		0x0045,
		0x0046,
		0x0047,
		0x0050,
		0x0051,
		0x0052,
		0x0053,
		0x0054,
		0x0055,
		0x0056,
		0x0057,
		0x0058,
		0x0059,
		0x005A,
		0x0064,
		0x0065,
		0x0070,
		0x0071,
		0x0072,
		0x0073,
		0x0074,
		0x007A,
		0x0080,
		0x0093,
		0x0095,
		0x0100,
		0x0102:
		r.Value = _dWordMarshal(b, v) // 设置
	case 0x0010,
		0x0011,
		0x0012,
		0x0013,
		0x0014,
		0x0015,
		0x0016,
		0x0017,
		0x001A,
		0x001D,
		0x0040,
		0x0041,
		0x0042,
		0x0043,
		0x0044,
		0x0048,
		0x0049,
		0x0083:
		r.Value = _stringMarshal(b, v)
	case 0x0031,
		0x005B,
		0x005C,
		0x005D,
		0x005E,
		0x0101,
		0x0103:
		r.Value = _wordMarshal(b, v)
	case 0x0081,
		0x0082,
		0x0084,
		0x0090,
		0x0091,
		0x0092,
		0x0094:
		r.Value = _byteMarshal(b, v)
	case 0x0075:
		r.Value = _0075Marshal(b, v)
	case 0x0076:
		r.Value = _0076Marshal(b, v)
	case 0x0077:
		r.Value = _0077Marshal(b, v)
	case 0x0079:
		r.Value = _0079Marshal(b, v)
	case 0x007B:
		r.Value = _007BMarshal(b, v)
	case 0x007C:
		r.Value = _007CMarshal(b, v)
	case 0x0110:
		r.Value = _bytesMarshal(b, v)
	case 0xF364:
		r.Value = _adasMarshal(b, v)
	case 0xF365:
		r.Value = _dsmMarshal(b, v)
	case 0xF366: // 胎压监测系统参数，见表 41212
		r.Value = _tpmsMarshal(b, v)
	case 0xF367: // 盲区监测系统参数，见表 41313
		r.Value = _bsdMarshal(b, v)
	default:
		r.Value = b.Bytes
	}
	r.ID = fmt.Sprintf("0x%04x", id)
	return
}
